身為並發(concurrency)小能手的 Go 的重要特色
有了 channel 好像幾乎不需要 lock (例如 mutex)了呢
2021/10/14 更新:Go 與 concurrency
雖然還有一些東西沒介紹到,例如 closure(閉包),
但感覺還是趕快看看別的程式碼會比較好玩一點XD
明天要爬山不知道有沒有空好好來看 被選召的 Gopher 們,從零開始探索 Golang, Istio, K8s 數碼微服務世界 系列 系列呢?
Go 的特點就是不需要特別 import 其他的模組,
內建的 go
這個關鍵字就能夠開啟類似 thread 的 goroutine,
並透過 Go Runtime Scheduler 排程使這些 goroutines 輪流跑。
至於 parallelism 要看硬體支援,也需要額外設定。
如果對於 concurrency(並發) / parallelism(並行) 的差別不熟悉可以參考 Concurrency is not parallelism 或 Google 圖片。
只要在 function 前加一個 go
就可以開一個 goroutine(thread)go f(x, y)
main 本身也是一個 goroutine
我個人覺得沒有很好理解的觀念,注意一開始不要把 channel 當成 buffer 理解。
看Go 的並發:Goroutine 與 Channel 介紹,以 「推入」「拉出」channel 來比喻,我覺得比 send / receive 還好懂一點。
ch := make(chan int) // create a channel
ch <- v // Send v to channel ch.
v := <-ch // Receive from ch, and
// assign value to v.
有一方在 send / receive 時,除非有另一方做 receive / send,不然就會 block(阻塞)在那
但我自己感覺只有 <- 才有 block 住?Channels的第20行的y拔掉後,main 就不會再等,直接 exit。
for i := range ch
直到 close(ch)
永遠只有 sender 該做 close 的動作。
因為只有他知道什麼時候再也不會 send 任何東西了,而如果給關閉的 channel 送東西的話會導致 panic。
channel 不是檔案不一定要 close
只有當 receiver 在跑回圈,例如印出 channel 接到的值,因為需要知道 sender 已經傳完了所以需要 close。
select
當某個 goroutine 要拉取 channel 的資料而可能需要等待時,當下就 block 住而不能處理其他事情。
如果這是處理畫面的 goroutine,就等於卡在那而不能有狀態條或其他等等回饋。
使用 select,case <- ch
先試著拉,如果塞住就看別的 case,
直到有一個 channel 有送到值 或是 最後使用 default case。
select {
case <-ch: // Channel 中有資料執行此區域
fmt.Println("main goroutine finished")
return
default: // Channel 阻塞的話執行此區域
fmt.Println("WAITING...")
time.Sleep(500 * time.Millisecond)
}
select 有點像 switch,但每個 case 都是拉拉看某個 channel 資料是否另一方送來了。
推入 / 拉出的時間不對等時(例如有一方有比較複雜的運算),就會造成等待。
如果有 buffer,推入時就不用等到有人拉出才能繼續推了;
只有當 buffer 滿的時候會 block,也就是不能再推入了。
ch := make(chan int, 2)